﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;
using SerialCommunication;
using System.Data;
using MyClass;

namespace GPS_DB
{
    class DotGPS
    {
        private const long HEADID = 0x73626142;
        private const long TAILID = 0x61526255;
        private const string VER = "Ver: 2.0.0.2";
        long starttick;

        private struct HEAD
        {
            public int MaxD;    //最大同线路站距离
            public int Lon1;    //缺省本站左上角相对经度
            public int Lat1;    //缺省本站左上角相对纬度
            public int Lon2;    //缺省本站右下角相对经度
            public int Lat2;    //缺省本站右下角相对纬度
            public int Lon3;    //缺省本站左下角相对经度
            public int Lat3;    //缺省本站左下角相对纬度
            public int Lon4;    //缺省本站右上角相对经度
            public int Lat4;    //缺省本站右上角相对纬度
            public int RdNum;   //线路调度区段数量
            public int StNum;   //车站数量
            public int RgNum;  //选择区域数量
            public int SwNum;   //切换点数据数量

            public DateTime UpdateTime;
            public long FileLength;
        }
        private HEAD FileHead;
        private struct ROAD
        {
            public int ID;
            public string roadname;
            public string dispname;
            public string mode;
            public string DispPhone1;
            public string StPhone1;
            public string DispPhone2;
            public string StPhone2;
        }
        private ROAD[] roads;
        private struct STATION
        {
            public string roadname;
            public string dispname;
            public string mode;
            public string stationname;
            public int ID;
            public int sphone;
            public int xphone;
            public string longitude;
            public string latitude;
            public int property;
            public int lon1;
            public int lat1;
            public int lon2;
            public int lat2;
            public int lon3;
            public int lat3;
            public int lon4;
            public int lat4;
            public int nextstation1;
            public int nextstation2;
            public int nextstation3;
            public int nextstation4;
        }
        private STATION[] stations;
        private struct REGION
        {
            public string longitude;
            public string latitude;
            public object[] roadname;
            public object[] dispname;
            public int[] lonlat;
            public object[] invalid;
        }
        private REGION[] regions;
        private struct SWITCH
        {
            public string longitude;
            public string latitude;
            public string[] roadname;
            public string[] dispname;
            public int[] lonlat;
            public object[] invalid;
        }
        private SWITCH[] switchs;

        private struct PHONEBOOK
        {
            public string roadname;
            public string dispatchname;
            public string stationname;
            public int phone;
        }
        private PHONEBOOK[] phones;

        private byte[] HeadArray = new byte[512];



        public void CreatDotGpsFile()
        {
            try
            {
                bool flag = false;
                OpenFileDialog openFD = new OpenFileDialog();
                openFD.Filter = "DataBase File(*.xls)|*.xls;*.xlsx";
                openFD.Title = "Please select the DataBase File";
                openFD.InitialDirectory = LrnS.GetItem("dotgpscreationfile");
                if (openFD.ShowDialog() == DialogResult.OK)
                {
                    LrnS.SaveItem("dotgpscreationfile", Path.GetDirectoryName(openFD.FileName));
                    starttick = DateTime.Now.Ticks;
                    string path_dir = Application.StartupPath + "\\点GPS\\";
                    if (Directory.Exists(path_dir))
                        Directory.Delete(path_dir, true);

                    DataSet ds = GF.DsFromExcel(openFD.FileName);
                    if (!readinDS(ds))
                        return;

                    if (!DataBaseCheck())
                        return;

                    byte[] RdData = GetDispatchData();
                    byte[] StData = GetStationData();
                    byte[] RgData = GetRegionData();
                    byte[] QhData = GetSwitchData();
                    flag = Combine(RdData, StData, RgData, QhData);

                }
                if (flag == true)
                    MessageBox.Show("生成完成！ \r\n用时：" +
                        ((DateTime.Now.Ticks - starttick) / 10000000).ToString() + "." +
                        ((DateTime.Now.Ticks - starttick) % 10000000).ToString() + "秒"
                        , ".Gps数据库");
            }
            catch (Exception er)
            {
                MessageBox.Show(er.Message);
            }
        }

        public void findPhones()
        {
            OpenFileDialog openroads = new OpenFileDialog();
            openroads.Filter = "roads file(*.txt)|*.txt";
            openroads.Title = "Please select file that contains the roads you want";
            openroads.InitialDirectory = LrnS.GetItem("findPhonesroadsfile");
            ArrayList roadnames = new ArrayList();

            if (openroads.ShowDialog() == DialogResult.OK)
            {
                LrnS.SaveItem("findPhonesroadsfile", Path.GetDirectoryName(openroads.FileName));

                roadnames.Clear();
                using (TextReader fs = File.OpenText(openroads.FileName))
                {
                    string readStr = "";

                    while (true)
                    {
                        readStr = fs.ReadLine();
                        if (readStr == null)
                            break;
                        else
                        {
                            if (readStr == "\r\n")
                                continue;
                            if (readStr.Contains("\r\n"))
                                readStr = readStr.Substring(0, readStr.IndexOf("\r\n"));

                            roadnames.Add(readStr);
                        }
                    }
                    fs.Close();
                }
            }
            else
            {
                return;
            }

            OpenFileDialog openFD = new OpenFileDialog();
            openFD.Filter = "DataBase File(*.xls)|*.xls";
            openFD.Title = "Please select the DataBase File";
            openFD.InitialDirectory = LrnS.GetItem("FindPhonesfile");
            if (openFD.ShowDialog() == DialogResult.OK)
            {
                LrnS.SaveItem("FindPhonesfile", Path.GetDirectoryName(openFD.FileName));
                starttick = DateTime.Now.Ticks;
                string path_dir = Application.StartupPath + "\\点GPS\\";
                if (Directory.Exists(path_dir))
                    Directory.Delete(path_dir, true);

                DataSet ds = GF.DsFromExcel(openFD.FileName);
                if (!readinDS(ds))
                    return;

                if (!DataBaseCheck())
                    return;

                if (!Directory.Exists(path_dir))
                    Directory.CreateDirectory(path_dir);
                string path_file = path_dir + "FindPhones.txt";

                using (FileStream fs = new FileStream(path_file, FileMode.Create))
                {
                    TextWriter wt = new StreamWriter(fs, Encoding.Default);
                    //fs.Seek(0, SeekOrigin.End);

                    wt.WriteLine(findPhoneData(roadnames));

                    wt.Close();
                    fs.Close();
                }
                MessageBox.Show("生成完成！ \r\n用时：" +
                ((DateTime.Now.Ticks - starttick) / 10000000).ToString() + "." +
                ((DateTime.Now.Ticks - starttick) % 10000000).ToString() + "秒"
                , "Phone Book!");
            }

        }
        private bool stringArrContains(ArrayList arr,string str)
        {
            string temp;
            for (int i = 0; i < arr.Count; i++)
            {
                temp = (string)arr[i];
                if (temp == str)
                    return true;
                if(str.Contains(temp))
                    return true;
                if(temp.Contains(str))
                    return true;
            }
            return false;
        }

        private string findPhoneData(ArrayList roadnames)
        {
            string error = "";
            string result = "";
            phones = new PHONEBOOK[FileHead.StNum * 2];

            #region getValue
            for (int i = 0; i < FileHead.StNum; i++)
            {
                phones[i * 2].roadname = stations[i].roadname;
                phones[i * 2].dispatchname = stations[i].dispname;
                phones[i * 2].stationname = stations[i].stationname;
                phones[i * 2].phone = stations[i].sphone;

                phones[i * 2 + 1].roadname = stations[i].roadname;
                phones[i * 2 + 1].dispatchname = stations[i].dispname;
                phones[i * 2 + 1].stationname = stations[i].stationname;
                phones[i * 2 + 1].phone = stations[i].xphone;

            }
            #endregion

            #region delete duplicate and ivalid
            for (int i = 0; i < FileHead.StNum * 2; i++)
            {
                if (phones[i].phone == 0)
                {
                    phones[i].stationname = "";
                    continue;
                }
                for (int j = i + 1; j < FileHead.StNum * 2; j++)
                {
                    if (phones[i].roadname == phones[j].roadname &&
                        phones[i].dispatchname == phones[j].dispatchname)
                    {
                        if (phones[i].stationname == phones[j].stationname &&
                            phones[i].phone == phones[j].phone)
                        {
                            phones[i].stationname = "";
                            phones[i].phone = 0;
                            break;
                        }
                    }
                }
            }
            for (int i = 0; i < FileHead.StNum * 2; i++)
            {
                for (int j = i + 1; j < FileHead.StNum * 2; j++)
                {
                    if (phones[i].roadname == phones[j].roadname &&
                        phones[i].dispatchname == phones[j].dispatchname)
                    {
                        if (phones[i].stationname != phones[j].stationname && phones[i].phone == phones[j].phone)
                        {
                            error = error + phones[i].stationname + " and " + phones[j].stationname + " :" +
                                phones[i].phone.ToString() + "\r\n";
                        }
                    }
                }
            }
            #endregion

            #region result
            string fengge = "\r\n**********************************************\r\n";
            for (int i = 0; i < FileHead.StNum * 2; i++)
            {
                if (phones[i].stationname == "")
                    continue;
                if (!stringArrContains(roadnames, phones[i].roadname))
                    continue;

                result = result + phones[i].roadname.PadRight(5, '　') + phones[i].dispatchname.ToString() + "\r\n";
            }
            for (int i = 0; i < FileHead.StNum * 2; i++)
            {
                if (phones[i].stationname == "")
                    continue;
                if (!stringArrContains(roadnames, phones[i].roadname))
                    continue;

                result = result + phones[i].stationname + "\r\n";
            }
            for (int i = 0; i < FileHead.StNum * 2; i++)
            {
                if (phones[i].stationname == "")
                    continue;
                if (!stringArrContains(roadnames, phones[i].roadname))
                    continue;

                result = result + phones[i].phone.ToString() + "\r\n";
            }
            #endregion

            return (result + fengge + error);
        }
        

        public void CreatPhoneBook()
        {
            OpenFileDialog openFD = new OpenFileDialog();
            openFD.Filter = "DataBase File(*.xls)|*.xls";
            openFD.Title = "Please select the DataBase File";
            openFD.InitialDirectory = LrnS.GetItem("phonebookcreationfile");
            if (openFD.ShowDialog() == DialogResult.OK)
            {
                LrnS.SaveItem("phonebookcreationfile", Path.GetDirectoryName(openFD.FileName));
                starttick = DateTime.Now.Ticks;
                string path_dir = Application.StartupPath + "\\点GPS\\";
                if (Directory.Exists(path_dir))
                    Directory.Delete(path_dir, true);

                DataSet ds = GF.DsFromExcel(openFD.FileName);
                if (!readinDS(ds))
                    return;

                if (!DataBaseCheck())
                    return;

                if (!Directory.Exists(path_dir))
                    Directory.CreateDirectory(path_dir);
                string path_file = path_dir + "TelephoneBook.txt";

                using (FileStream fs = new FileStream(path_file, FileMode.Create))
                {
                    TextWriter wt = new StreamWriter(fs, Encoding.Default);
                    //fs.Seek(0, SeekOrigin.End);

                    wt.WriteLine(GetPhoneData());

                    wt.Close();
                    fs.Close();
                }
                MessageBox.Show("生成完成！ \r\n用时：" +
                ((DateTime.Now.Ticks - starttick) / 10000000).ToString() + "." +
                ((DateTime.Now.Ticks - starttick) % 10000000).ToString() + "秒"
                , "Phone Book!");
            }
            
        }

        private string GetPhoneData()
        {
            string error = "";
            string result="";
            phones = new PHONEBOOK[FileHead.StNum * 2];
            for (int i = 0; i < FileHead.StNum; i++)
            {
                phones[i * 2].stationname = stations[i].stationname;
                phones[i * 2].phone = stations[i].sphone;
                phones[i * 2 + 1].stationname = stations[i].stationname;
                phones[i * 2 + 1].phone = stations[i].xphone;

            }
            for (int i = 0; i < FileHead.StNum * 2; i++)
            {
                if (phones[i].stationname == "太南大西")
                    phones[i].stationname = "太原南";
                if (phones[i].stationname == "上海虹桥")
                    phones[i].stationname = "虹桥";
                if (phones[i].stationname == "葫芦")
                    phones[i].stationname = "古营盘";
                if (phones[i].stationname == "津西津保")
                    phones[i].stationname = "天津西";

            }
            #region delete duplicate and ivalid
            for (int i = 0; i < FileHead.StNum * 2; i++)
            {
                if (phones[i].stationname == "")
                    phones[i].stationname = "";

                if (phones[i].phone == 0)
                {
                    phones[i].stationname = "";
                    continue;
                }
                for (int j = i + 1; j < FileHead.StNum * 2; j++)
                {
                    if (phones[i].stationname == phones[j].stationname && phones[i].phone == phones[j].phone)
                    {
                        phones[i].stationname = "";
                        phones[i].phone = 0;
                        break;
                    }
                    if (phones[i].stationname != phones[j].stationname && phones[i].phone == phones[j].phone)
                    {
                        error =error+ phones[i].stationname + " and " + phones[j].stationname + " :" +
                            phones[i].phone.ToString() + "\r\n";
                    }
                }
            }
            #endregion

            #region result
            for (int i = 0; i < FileHead.StNum * 2; i++)
            {
                if (phones[i].stationname == "")
                    continue;

                result = result + phones[i].stationname.PadRight(4, '　')+"=" + phones[i].phone.ToString() + "\r\n";
            }
            #endregion

            return (result + error);
        }

        private bool readinDS(DataSet ds)
        {
            #region Sheets Check
            if (!ds.Tables.Contains("set$"))
            {
                MessageBox.Show("Not contains sheet:set!");
                return false;
            }
            if (!ds.Tables.Contains("线路调度区段$"))
            {
                MessageBox.Show("Not contains sheet:线路调度区段!");
                return false;
            }
            if (!ds.Tables.Contains("车站$"))
            {
                MessageBox.Show("Not contains sheet:车站!");
                return false;
            }
            if (!ds.Tables.Contains("线路选择区间$"))
            {
                MessageBox.Show("Not contains sheet:线路选择区间!");
                return false;
            }
            if (!ds.Tables.Contains("切换点$"))
            {
                MessageBox.Show("Not contains sheet:切换点!");
                return false;
            }
            #endregion

            #region FileHead
            DataTable tSet = ds.Tables["set$"];
            FileHead.MaxD = int.Parse(tSet.Rows[0][1].ToString());
            FileHead.Lon1 = int.Parse(tSet.Rows[1][1].ToString());
            FileHead.Lat1 = int.Parse(tSet.Rows[2][1].ToString());
            FileHead.Lon2 = int.Parse(tSet.Rows[3][1].ToString());
            FileHead.Lat2 = int.Parse(tSet.Rows[4][1].ToString());
            FileHead.Lon3 = int.Parse(tSet.Rows[5][1].ToString());
            FileHead.Lat3 = int.Parse(tSet.Rows[6][1].ToString());
            FileHead.Lon4 = int.Parse(tSet.Rows[7][1].ToString());
            FileHead.Lat4 = int.Parse(tSet.Rows[8][1].ToString());
            FileHead.RdNum = int.Parse(tSet.Rows[9][1].ToString());
            FileHead.StNum = int.Parse(tSet.Rows[10][1].ToString());
            FileHead.RgNum = int.Parse(tSet.Rows[11][1].ToString());
            FileHead.SwNum = int.Parse(tSet.Rows[12][1].ToString());
            #endregion

            #region variables new()
            roads = new ROAD[FileHead.RdNum];
            stations = new STATION[FileHead.StNum];
            regions = new REGION[FileHead.RgNum];
            switchs = new SWITCH[FileHead.SwNum];
            #endregion

            #region Amount Check
            if (MaxRowInTable(ds.Tables["线路调度区段$"]) != FileHead.RdNum)
            {
                MessageBox.Show("Road Number Error!");
                return false;
            }

            if (MaxRowInTable(ds.Tables["车站$"]) != FileHead.StNum)
            {
                MessageBox.Show("Station Number Error!");
                return false;
            }

            if (MaxRowInTable(ds.Tables["线路选择区间$"]) != FileHead.RgNum)
            {
                MessageBox.Show("Region Number Error!");
                return false;
            }

            if (MaxRowInTable(ds.Tables["切换点$"]) != FileHead.SwNum)
            {
                MessageBox.Show("QieHuangDian Number Error!");
                return false;
            }
            #endregion


            #region road
            DataTable tRd = ds.Tables["线路调度区段$"];
            for (int count = 0; count < FileHead.RdNum; count++)
            {
                roads[count].ID = int.Parse(tRd.Rows[count][1].ToString().Trim());
                roads[count].roadname = tRd.Rows[count][2].ToString().Trim();
                roads[count].dispname = tRd.Rows[count][3].ToString().Trim();
                roads[count].mode = tRd.Rows[count][4].ToString().Trim();
                roads[count].DispPhone1 = tRd.Rows[count][5].ToString().Trim();
                roads[count].StPhone1 = tRd.Rows[count][6].ToString().Trim();
                roads[count].DispPhone2 = tRd.Rows[count][7].ToString().Trim();
                roads[count].StPhone2 = tRd.Rows[count][8].ToString().Trim();
            }
            #endregion

            #region station
            DataTable tSt = ds.Tables["车站$"];
            for (int count = 0; count < FileHead.StNum; count++)
            {
                stations[count].roadname = tSt.Rows[count][0].ToString().Trim();
                stations[count].dispname = tSt.Rows[count][1].ToString().Trim();
                stations[count].mode = tSt.Rows[count][2].ToString().Trim();
                stations[count].stationname = tSt.Rows[count][3].ToString().Trim();
                stations[count].ID = int.Parse(tSt.Rows[count][4].ToString().Trim());
                stations[count].sphone = int.Parse(tSt.Rows[count][5].ToString().Trim());
                stations[count].xphone = int.Parse(tSt.Rows[count][6].ToString().Trim());
                stations[count].longitude = tSt.Rows[count][7].ToString().Trim();
                stations[count].latitude = tSt.Rows[count][8].ToString().Trim();
                stations[count].property = int.Parse(tSt.Rows[count][9].ToString().Trim());
                stations[count].lon1 = int.Parse(tSt.Rows[count][10].ToString().Trim());
                stations[count].lat1 = int.Parse(tSt.Rows[count][11].ToString().Trim());
                stations[count].lon2 = int.Parse(tSt.Rows[count][12].ToString().Trim());
                stations[count].lat2 = int.Parse(tSt.Rows[count][13].ToString().Trim());
                stations[count].lon3 = int.Parse(tSt.Rows[count][14].ToString().Trim());
                stations[count].lat3 = int.Parse(tSt.Rows[count][15].ToString().Trim());
                stations[count].lon4 = int.Parse(tSt.Rows[count][16].ToString().Trim());
                stations[count].lat4 = int.Parse(tSt.Rows[count][17].ToString().Trim());
                stations[count].nextstation1 = int.Parse(tSt.Rows[count][18].ToString().Trim());
                stations[count].nextstation2 = int.Parse(tSt.Rows[count][19].ToString().Trim());
                stations[count].nextstation3 = int.Parse(tSt.Rows[count][20].ToString().Trim());
                stations[count].nextstation4 = int.Parse(tSt.Rows[count][21].ToString().Trim());
            }
            #endregion

            #region region
            DataTable tRg = ds.Tables["线路选择区间$"];
            for (int count = 0; count < FileHead.RgNum; count++)
            {
                regions[count].lonlat = new int[4];
                regions[count].roadname = new object[8];
                regions[count].dispname = new object[8];
                regions[count].invalid = new object[7];
                regions[count].longitude = tRg.Rows[count][1].ToString().Trim();
                regions[count].latitude = tRg.Rows[count][2].ToString().Trim();

                for (int i = 0; i < 8; i++)
                {
                    regions[count].roadname[i] = tRg.Rows[count][3 + 2 * i];
                    regions[count].dispname[i] = tRg.Rows[count][4 + 2 * i];
                }
                for (int i = 0; i < 4; i++)
                {
                    regions[count].lonlat[i] = int.Parse(tRg.Rows[count][19 + i].ToString().Trim());
                }
                for (int i = 0; i < 7; i++)
                {
                    regions[count].invalid[i] = tRg.Rows[count][23 + i];
                }
            }
            #endregion

            #region switch
            DataTable tSw = ds.Tables["切换点$"];
            for (int count = 0; count < FileHead.SwNum; count++)
            {
                switchs[count].roadname = new string[2];
                switchs[count].dispname = new string[2];
                switchs[count].lonlat = new int[4];
                switchs[count].invalid = new object[8];
                switchs[count].longitude = tSw.Rows[count][0].ToString().Trim();
                switchs[count].latitude = tSw.Rows[count][1].ToString().Trim();
                for (int i = 0; i < 2; i++)
                {
                    switchs[count].roadname[i] = tSw.Rows[count][2 + 2 * i].ToString().Trim();
                    switchs[count].dispname[i] = tSw.Rows[count][3 + 2 * i].ToString().Trim();
                }
                for (int i = 0; i < 4; i++)
                {
                    switchs[count].lonlat[i] = int.Parse(tSw.Rows[count][6 + i].ToString().Trim());
                }

                for (int i = 0; i < 8; i++)
                {
                    switchs[count].invalid[i] = tSw.Rows[count][10 + i];
                }
            }
            #endregion

            return true;
        }

        private bool DataBaseCheck()
        {
            #region 车站 Check
            string maxDispsName = "";
            string lastStationName = "", lastDispName = "", lastMode = "";
            int maxStationNumber = 0, dispCount = 0;

            for (int count = 0; count < stations.Length; count++)
            {
                #region stationnameLength Check
                byte[] temp = Encoding.Default.GetBytes(stations[count].stationname);
                if (temp.Length > 8)
                {
                    MessageBox.Show((count + 2).ToString() + ":station name too long");
                }

                #endregion

                #region Property Check
                if (stations[count].stationname.EndsWith("*"))
                {
                    if (stations[count].property != 21)
                    {
                        MessageBox.Show((count + 2).ToString() + ":wrong Proterty ");
                        return false;
                    }
                }
                else
                {
                    if (stations[count].property != 17)
                    {
                        MessageBox.Show((count + 2).ToString() + ":wrong Proterty ");
                        return false;
                    }
                }
                #endregion

                #region Dulicate Station Check
                if (lastStationName == stations[count].stationname && lastDispName == stations[count].dispname)
                {
                    MessageBox.Show(count.ToString() + ":Duplicate station name");
                    return false;
                }
                #endregion

                #region Mode Check
                if (stations[count].dispname == lastDispName)
                {
                    if (stations[count].mode != lastMode)
                    {
                        MessageBox.Show("same dispatch different Mode: " + stations[count].roadname);
                        return false;
                    }
                }
                #endregion

                #region Calculate maximum stations in same dispatch
                if (stations[count].dispname == lastDispName)
                    dispCount++;
                else
                {
                    if (maxStationNumber < dispCount)
                    {
                        maxDispsName = lastDispName;
                        maxStationNumber = dispCount;
                        if (maxStationNumber >= 560)
                            MessageBox.Show(maxStationNumber.ToString() + " stations in: " + maxDispsName);
                    }
                    dispCount = 1;
                }
                #endregion

                if (stations[count].property == 17)
                {
                    lastStationName = stations[count].roadname;
                }
                lastDispName = stations[count].dispname;
                lastMode = stations[count].mode;
            }
            

            #region ID Check
            for (int i = 0; i < FileHead.StNum; i++)
            {
                if (stations[i].property != 17)
                    continue;

                for (int j = i + 1; j < FileHead.StNum; j++)
                {
                    if (stations[j].property != 17)
                        continue;
                    if (stations[i].ID == stations[j].ID)
                    {
                        MessageBox.Show((i + 2).ToString() + " :Duplicate station ID");
                        return false;
                    }
                }
            }
            #endregion
            #endregion

            return true;
        }

        private byte[] GetDispatchData()
        {
            int rdSec = SectorCalculator(FileHead.RdNum);
            byte[] rdBytes = new byte[rdSec * 512];
            rdBytes.Initialize();

            for (int index = 0; index < FileHead.RdNum; index++)
            {
                GF.PutLongToByteArr(roads[index].ID, rdBytes, index * 64, 2);
                for (int j = 0; j < 8; j++)
                {
                    rdBytes[2 + j + index * 64] = 0x20;
                }
                Encoding.Default.GetBytes(roads[index].roadname, 0, roads[index].roadname.Length, rdBytes, 2 + index * 64);
                for (int j = 0; j < 21; j++)
                {
                    rdBytes[10 + j + index * 64] = 0x20;
                }
                Encoding.Default.GetBytes(roads[index].dispname, 0, roads[index].dispname.Length, rdBytes, 10 + index * 64);
                rdBytes[31 + index * 64] = byte.Parse(roads[index].mode);

                for (int j = 0; j < 32; j++)
                {
                    rdBytes[32 + j + index * 64] = 0x20;
                }
                Encoding.Default.GetBytes(roads[index].DispPhone1, 0, roads[index].DispPhone1.Length, rdBytes, 32 + index * 64);

                Encoding.Default.GetBytes(roads[index].StPhone1, 0, roads[index].StPhone1.Length, rdBytes, 40 + index * 64);

                Encoding.Default.GetBytes(roads[index].DispPhone2, 0, roads[index].DispPhone2.Length, rdBytes, 48 + index * 64);

                Encoding.Default.GetBytes(roads[index].StPhone2, 0, roads[index].StPhone2.Length, rdBytes, 56 + index * 64);

            }
            return rdBytes;
        }
        private byte[] GetStationData()
        {
            int stSec = SectorCalculator(FileHead.StNum);
            byte[] stBytes = new byte[stSec * 512];
            stBytes.Initialize();

            int roadindex, nxtST1 = 1, nxtST2 = 1, nxtST3 = 1, nxtST4 = 1;
        
            for (int index = 0; index < FileHead.StNum; index++)
            {
                //线路序号
                roadindex = FindRoadIndex(stations[index].roadname, stations[index].dispname);
                if (roadindex == 0)
                {
                    MessageBox.Show("Can't find road: " + stations[index].roadname + ":" + stations[index].dispname);
                }
                GF.PutLongToByteArr(roadindex, stBytes, index * 64, 2);

                //车站名称
                for (int j = 0; j < 8; j++)
                {
                    stBytes[2 + j + index * 64] = 0x20;
                }
                Encoding.Default.GetBytes(stations[index].stationname, 0, stations[index].stationname.Length, stBytes, 2 + index * 64);

                //车站代码
                GF.PutLongToByteArr(stations[index].ID, stBytes, 10 + index * 64, 2);

                //车站电话号码
                GF.PutLongToByteArr(stations[index].sphone, stBytes, 12 + index * 64, 4);
                GF.PutLongToByteArr(stations[index].xphone, stBytes, 16 + index * 64, 4);

                //车站经纬度
                for (int ii = 0; ii < 9; ii++)
                {
                    stBytes[20 + index * 64 + ii] = 0xFF;
                } 
                LonLatChangeToArr(stations[index].longitude, stations[index].latitude).CopyTo(stBytes, 20 + index * 64);

                //信息点属性
                GF.PutLongToByteArr(stations[index].property, stBytes, 29 + index * 64, 1);

                //本站左上角相对经度
                GF.PutLongToByteArr(stations[index].lon1, stBytes, 30 + index * 64, 2);

                //本站左上角相对纬度
                GF.PutLongToByteArr(stations[index].lat1, stBytes, 32 + index * 64, 2);

                //本站右下角相对经度
                GF.PutLongToByteArr(stations[index].lon2, stBytes, 34 + index * 64, 2);

                //本站右下角相对纬度
                GF.PutLongToByteArr(stations[index].lat2, stBytes, 36 + index * 64, 2);

                //本站左下角相对经度
                GF.PutLongToByteArr(stations[index].lon3, stBytes, 38 + index * 64, 2);

                //本站左下角相对纬度
                GF.PutLongToByteArr(stations[index].lat3, stBytes, 40 + index * 64, 2);

                //本站右上角相对经度
                GF.PutLongToByteArr(stations[index].lon4, stBytes, 42 + index * 64, 2);

                //本站右上角相对纬度
                GF.PutLongToByteArr(stations[index].lat4, stBytes, 44 + index * 64, 2);

                nxtST1 = 1;
                nxtST2 = 1;
                nxtST3 = 1;
                nxtST4 = 1;
                //本站前站索引1
                if (stations[index].nextstation1 != 0)
                {
                    nxtST1 = FindStationIndex(stations[index].nextstation1);
                    GF.PutLongToByteArr(nxtST1, stBytes, 46 + index * 64, 4);
                }

                //本站前站索引2
                if (stations[index].nextstation2 != 0)
                {
                    nxtST2 = FindStationIndex(stations[index].nextstation2);
                    GF.PutLongToByteArr(nxtST2, stBytes, 50 + index * 64, 4);
                }

                //本站前站索引3
                if (stations[index].nextstation3 != 0)
                {
                    nxtST3 = FindStationIndex(stations[index].nextstation3);
                    GF.PutLongToByteArr(nxtST3, stBytes, 54 + index * 64, 4);
                }

                //本站前站索引4
                if (stations[index].nextstation4 != 0)
                {
                    nxtST4 = FindStationIndex(stations[index].nextstation4);
                    GF.PutLongToByteArr(nxtST4, stBytes, 58 + index * 64, 4);
                }
                if (nxtST1 * nxtST2 * nxtST3 * nxtST4 == 0)
                    MessageBox.Show("Can't NXT_ST of" + stations[index].roadname + " " + stations[index].stationname);
            }
            return stBytes;
        }
        private byte[] GetRegionData()
        {
            int result;
            int regionnum = FileHead.RgNum;
            int rgSec = SectorCalculator(regionnum);
            byte[] rgBytes = new byte[rgSec * 512];
            rgBytes.Initialize();

            REGION rg;
            for (int index = 0; index < regionnum; index++)
            {
                rg = regions[index];

                #region longitude latitude
                LonLatChangeToArr(rg.longitude, rg.latitude).CopyTo(rgBytes, 2 + 64 * index);
                #endregion

                #region region
                for (int i = 0; i < 8; i++)
                {
                    if (!GF.IsEmpty( rg.roadname[i]))
                    {
                        string LineName8 = rg.roadname[i].ToString().Trim();//RD_ID8
                        string LineDispatchName8 = rg.dispname[i].ToString().Trim();
                        result = FindRoadIndex(LineName8, LineDispatchName8);
                        if (result == 0)
                            MessageBox.Show("Can't find: " + LineName8 + " " + LineDispatchName8);
                        GF.PutLongToByteArr(result, rgBytes, 12 + 2 * i + 64 * index, 2);
                    }
                }
                #endregion

                #region lon and lat width
                for (int i = 0; i < 4; i++)
                {
                    int LonLatWidth = rg.lonlat[i];
                    GF.PutLongToByteArr(LonLatWidth, rgBytes, 28 + 2 * i + 64 * index, 2);
                }
                #endregion

                #region Unvalid stations
                for (int i = 0; i < 7; i++)
                {
                    if (!GF.IsEmpty(rg.invalid[i]))
                    {
                        int invalidStationID = int.Parse(rg.invalid[i].ToString().Trim());
                        if (invalidStationID == 0)
                            break;
                        int invalidStationIndex = FindStationIndex(invalidStationID);
                        if (invalidStationIndex == 0)
                            MessageBox.Show("Can't find: " + invalidStationID.ToString());
                        GF.PutLongToByteArr(invalidStationIndex, rgBytes, 36 + 4 * i + 64 * index, 4);
                    }
                }
                #endregion
            }

            return rgBytes;
        }
        private byte[] GetSwitchData()
        {
            int qhSec = SectorCalculator(FileHead.SwNum);
            byte[] swBytes = new byte[qhSec * 512];
            swBytes.Initialize();

            SWITCH sw;

            for (int index = 0; index < FileHead.SwNum; index++)
            {
                sw = switchs[index];

                int Qhd_ID = index + 1;//ID
                GF.PutLongToByteArr(Qhd_ID, swBytes, 0 + 64 * index, 2);

                LonLatChangeToArr(sw.longitude, sw.latitude).CopyTo(swBytes, 2 + 64 * index);

                int ID1 = FindRoadIndex(sw.roadname[0], sw.dispname[0]);
                if (ID1 == 0)
                    MessageBox.Show("Can't find " + sw.roadname[0] + " " + sw.dispname[0]);
                int ID2 = FindRoadIndex(sw.roadname[1], sw.dispname[1]);
                if (ID2 == 0)
                    MessageBox.Show("Can't find " + sw.roadname[1] + " " + sw.dispname[1]);
                GF.PutLongToByteArr(ID1, swBytes, 12 + 64 * index, 2);
                GF.PutLongToByteArr(ID2, swBytes, 14 + 64 * index, 2);

                for (int i = 0; i < 4; i++)
                {
                    int Re_Lon1 = sw.lonlat[i];
                    GF.PutLongToByteArr(Re_Lon1, swBytes, 16 + 2 * i + 64 * index, 2);
                }
                for (int i = 0; i < 8; i++)   //GR# Index[?]:该区间数据对哪些站无效：存在时每个车站占用4字节，低位在前
                {
                    if (!GF.IsEmpty( sw.invalid[i]))
                    {
                        int invalidStationID = int.Parse(sw.invalid[i].ToString().Trim());
                        if (invalidStationID == 0)
                            break;
                        int invalidStationIndex = FindStationIndex(invalidStationID);
                        if (invalidStationIndex == 0)
                            MessageBox.Show("Can't find:" + sw.invalid[i].ToString());
                        GF.PutLongToByteArr(invalidStationIndex, swBytes, 24 + 4 * i + 64 * index, 4);
                    }
                }
            }
            return swBytes;
        }
        private int cell_byte(int unit, int total)
        {
            int temp = total / unit;
            if(temp * unit == total)
                return temp;
            return temp + 1;
        }
        private bool Combine(byte[] rddata, byte[] stdata, byte[] rgdata, byte[] qhdata)
        {
            long headlength = 0,offset;
            long dotGPSlength;
            long db_gps_part_length = 512 * 2 + rddata.Length + stdata.Length + rgdata.Length + qhdata.Length;

            #region dotGPS file buffer allocate
            dotGPSlength = headlength + db_gps_part_length;
            byte[] FinalArray = new byte[dotGPSlength];
            #endregion

            #region file head and tabloid
            if (headlength == 1024)
            {
                #region 文件头 1024 Bytes value initialization
                for (int i = 0; i < headlength; i++)
                {
                    FinalArray[i] = (byte)i;
                }
                #endregion

                #region 文件头 1024 Bytes value set
                const int stunit = 0x9600;
                int modulecnt = 5 + cell_byte(stunit, stdata.Length);

                ushort[] moduleID = new ushort[modulecnt];
                ushort[] moduleVER = new ushort[modulecnt];
                int[] moduleOffset = new int[modulecnt];
                int[] moduleLength = new int[modulecnt];

                int index;

                //数据库头
                index = 0;
                moduleID[index] = 0x0001;
                moduleVER[index] = 0x0016;
                moduleOffset[index] = 0x00000400;
                moduleLength[index] = 0x00000200;

                //区段
                index++;
                moduleID[index] = 0x1000;
                moduleVER[index] = 0x0014;
                moduleLength[index] = rddata.Length;

                //车站
                for (int i = 0; i < cell_byte(stunit, stdata.Length); i++)
                {
                    index++;
                    moduleID[index] = (ushort)(0x1000 + i);
                    moduleVER[index] = 0x0014;
                    if (i != cell_byte(stunit, stdata.Length) - 1)
                        moduleLength[index] = stunit;
                    else
                    {
                        if (index > 9)
                        {
                            moduleVER[index - 8] = 0x0016;
                            moduleVER[index - 7] = 0x0016;
                            moduleVER[index - 6] = 0x0016;
                            moduleVER[index - 5] = 0x0016;
                            moduleVER[index - 4] = 0x0016;
                            moduleVER[index - 3] = 0x0016;
                            moduleVER[index - 2] = 0x0016;
                            moduleVER[index - 1] = 0x0016;
                        }
                        moduleVER[index] = 0x0016;
                        moduleLength[index] = stdata.Length - stunit * i;
                    }
                }

                //区间
                index++;
                moduleID[index] = 0xC000;
                moduleVER[index] = 0x0014;
                moduleLength[index] = rgdata.Length;

                //切换点
                index++;
                moduleID[index] = 0xD000;
                moduleVER[index] = 0x0014;
                moduleLength[index] = qhdata.Length;

                //尾
                index++;
                moduleID[index] = 0xE000;
                moduleVER[index] = 0x0016;
                moduleLength[index] = 0x00000200;

                if (index != modulecnt - 1 || modulecnt >= 512 / 12)
                {
                    MessageBox.Show("摘要中的模块长度错误");
                    return false;
                }

                for (int i = 1; i < modulecnt; i++)
                {
                    moduleOffset[i] = moduleOffset[i - 1] + moduleLength[i - 1];
                }
                #endregion

                #region 文件头 1024 Bytes value copy
                FinalArray[0] = (byte)(dotGPSlength >> 0);//file length
                FinalArray[1] = (byte)(dotGPSlength >> 8);
                FinalArray[2] = (byte)(dotGPSlength >> 16);
                FinalArray[3] = (byte)(dotGPSlength >> 24);

                FinalArray[4] = (byte)(modulecnt >> 0);//module count
                FinalArray[5] = (byte)(modulecnt >> 8);

                for (int i = 0; i < modulecnt; i++)
                {
                    FinalArray[512 + 00 + i * 12] = (byte)(moduleID[i] >> 0);//module ID
                    FinalArray[512 + 01 + i * 12] = (byte)(moduleID[i] >> 8);

                    FinalArray[512 + 02 + i * 12] = (byte)(moduleVER[i] >> 0);//module version
                    FinalArray[512 + 03 + i * 12] = (byte)(moduleVER[i] >> 8);

                    FinalArray[512 + 04 + i * 12] = (byte)(moduleOffset[i] >> 0);//module offset
                    FinalArray[512 + 05 + i * 12] = (byte)(moduleOffset[i] >> 8);
                    FinalArray[512 + 06 + i * 12] = (byte)(moduleOffset[i] >> 16);
                    FinalArray[512 + 07 + i * 12] = (byte)(moduleOffset[i] >> 24);

                    FinalArray[512 + 08 + i * 12] = (byte)(moduleLength[i] >> 0);//module length
                    FinalArray[512 + 09 + i * 12] = (byte)(moduleLength[i] >> 8);
                    FinalArray[512 + 10 + i * 12] = (byte)(moduleLength[i] >> 16);
                    FinalArray[512 + 11 + i * 12] = (byte)(moduleLength[i] >> 24);

                }
                #region add CRC
                List<byte> tabarray = new List<byte>(FinalArray);
                ushort tabCRC = CRC16.CalculateCRC(tabarray, 512, 510);

                FinalArray[512 + 510] = (byte)(tabCRC % 256);
                FinalArray[512 + 511] = (byte)(tabCRC / 256);

                #endregion


                #endregion
            }
            offset = headlength;
            #endregion

            #region road/station/region/Qiehuan information set
            HeadArray.Initialize();
            GF.PutLongToByteArr(HEADID, HeadArray, 0, 4);
            FileHead.UpdateTime = DateTime.Now;
            HeadArray[11] = 0;
            HeadArray[10] = (byte)(FileHead.UpdateTime.Year / 0x100);
            HeadArray[9] = (byte)(FileHead.UpdateTime.Year % 0x100);
            HeadArray[8] = (byte)FileHead.UpdateTime.Month;
            HeadArray[7] = (byte)FileHead.UpdateTime.Day;
            HeadArray[6] = (byte)FileHead.UpdateTime.Hour;
            HeadArray[5] = (byte)FileHead.UpdateTime.Minute;
            HeadArray[4] = (byte)FileHead.UpdateTime.Second;
            Encoding.Default.GetBytes(VER, 0, 12, HeadArray, 12);
            FileHead.FileLength = db_gps_part_length;
            GF.PutLongToByteArr(FileHead.StNum, HeadArray, 24, 4);
            GF.PutLongToByteArr(FileHead.FileLength, HeadArray, 28, 4);
            GF.PutLongToByteArr(FileHead.MaxD, HeadArray, 32, 2);
            GF.PutLongToByteArr(FileHead.Lon1, HeadArray, 34, 2);
            GF.PutLongToByteArr(FileHead.Lat1, HeadArray, 36, 2);
            GF.PutLongToByteArr(FileHead.Lon2, HeadArray, 38, 2);
            GF.PutLongToByteArr(FileHead.Lat2, HeadArray, 40, 2);
            GF.PutLongToByteArr(FileHead.Lon3, HeadArray, 42, 2);
            GF.PutLongToByteArr(FileHead.Lat3, HeadArray, 44, 2);
            GF.PutLongToByteArr(FileHead.Lon4, HeadArray, 46, 2);
            GF.PutLongToByteArr(FileHead.Lat4, HeadArray, 48, 2);
            GF.PutLongToByteArr(FileHead.RdNum, HeadArray, 50, 2);
            GF.PutLongToByteArr(FileHead.StNum, HeadArray, 52, 4);
            GF.PutLongToByteArr(FileHead.RgNum, HeadArray, 56, 2);
            GF.PutLongToByteArr(FileHead.SwNum, HeadArray, 58, 2);

            ushort crc1 = GF.CRC(HeadArray, 4, 506);
            HeadArray[510] = (byte)(crc1 % 256);
            HeadArray[511] = (byte)(crc1 / 256);
            for (int i = 0; i < 512; i++)
            {
                FinalArray[offset + i] = HeadArray[i];
            }
            offset += 512;
            #endregion

            #region Road
            Array.Copy(rddata, 0, FinalArray, offset, rddata.Length);
            offset += rddata.Length;
            #endregion

            #region Station
            Array.Copy(stdata, 0, FinalArray, offset, stdata.Length);
            offset += stdata.Length;
            #endregion

            #region Region
            Array.Copy(rgdata, 0, FinalArray, offset, rgdata.Length);
            offset += rgdata.Length;
            #endregion

            #region Switch
            Array.Copy(qhdata, 0, FinalArray, offset, qhdata.Length);
            offset += qhdata.Length;
            #endregion

            #region 文件尾

            GF.PutLongToByteArr(TAILID, FinalArray, offset, 4);
            offset += 4;

            for (int i = 0; i < 24; i++)
            {
                FinalArray[offset + i] = HeadArray[4 + i];
            }
            offset += 24;

            //482 reserved bytes
            offset += 482;

            //GR# 新增  parameter ushort is not enough.
            ushort crcTailOld = GF.CRC(FinalArray, (ushort)(dotGPSlength - 512 + 4), 506);

            List<byte> there = new List<byte>(FinalArray);
            ushort tailCRC = CRC16.CalculateCRC(there, (int)(dotGPSlength - 512 + 4), 506);

            FinalArray[dotGPSlength - 2] = (byte)(tailCRC % 256);
            FinalArray[dotGPSlength - 1] = (byte)(tailCRC / 256);
            #endregion

            #region add whole CRC(from file tabloid to the end)
            if (headlength == 1024)
            {
                List<byte> wholearray = new List<byte>(FinalArray);
                ushort wholeCRC = CRC16.CalculateCRC(wholearray, 512, (int)(dotGPSlength - 512));

                FinalArray[20] = (byte)(wholeCRC % 256);
                FinalArray[21] = (byte)(wholeCRC / 256);
            }
            #endregion

            #region add file head CRC
            if (headlength == 1024)
            {
                List<byte> hArray = new List<byte>(FinalArray);
                ushort hCRC = CRC16.CalculateCRC(hArray, 0, 510);

                FinalArray[510] = (byte)(hCRC % 256);
                FinalArray[511] = (byte)(hCRC / 256);
            }
            #endregion

            #region Creat DotGps File
            string path_dir = Application.StartupPath + "\\点GPS\\";
            if (!Directory.Exists(path_dir))
                Directory.CreateDirectory(path_dir);
            string path_GPS = path_dir +
                FileHead.UpdateTime.Year.ToString() +
                FileHead.UpdateTime.Month.ToString("00") +
                FileHead.UpdateTime.Day.ToString("00") + ".GPS";

            string path_SMR = path_dir +
                FileHead.UpdateTime.Year.ToString() +
                FileHead.UpdateTime.Month.ToString("00") +
                FileHead.UpdateTime.Day.ToString("00") + ".SMR";

            if (File.Exists(path_GPS))
                File.Delete(path_GPS);
            if (File.Exists(path_SMR))
                File.Delete(path_SMR);
            using (FileStream fs1 = new FileStream(path_GPS, FileMode.Create, FileAccess.ReadWrite))
            {
                BinaryWriter w1 = new BinaryWriter(fs1);
                w1.Write(FinalArray, 0, (int)dotGPSlength);
                w1.Close();
                fs1.Close();
            }
            if (headlength == 1024)
            {
                using (FileStream fs1 = new FileStream(path_SMR, FileMode.Create, FileAccess.ReadWrite))
                {
                    BinaryWriter w1 = new BinaryWriter(fs1);
                    w1.Write(FinalArray, 0, (int)1024);
                    w1.Close();
                    fs1.Close();
                }
            }
            #endregion

            return true;
        }

        private int SectorCalculator(int numOf64Bytes)
        {
            int sec = numOf64Bytes / 8;
            if (numOf64Bytes % 8 != 0)
                sec++;
            return sec;
        }
        private int FindRoadIndex(string rdname, string dispname)
        {
            int count = 0, rdindex = 0;
            for (int i = 0; i < roads.Length; i++)
            {
                if (rdname == roads[i].roadname && dispname == roads[i].dispname)
                {
                    count++;
                    rdindex = i + 1;
                }
            }
            if (count == 1)
                return rdindex;
            return 0;
        }
        private int FindStationIndex(int id)
        {
            int count = 0, stindex = 0;
            for (int i = 0; i < stations.Length; i++)
            {
                if (id == stations[i].ID)
                {
                    count++;
                    stindex = i + 1;
                    return stindex;
                }
            }
            if (count == 1)
                return stindex;
            return 0;
        }
        private byte[] LonLatChangeToArr(string lon, string lat)
        {
            byte[] arr = new byte[9];
            lon = GF.GPSLonLatFormWithoutDos(lon);
            lat = GF.GPSLonLatFormWithoutDos(lat);
            lon = lon.PadLeft(9, '0');
            lat = lat.PadLeft(8, '0');
            arr[0] = (byte)GF.HexToBCD(ulong.Parse(lon.Substring(0, 1).ToString()), 2);
            arr[1] = (byte)GF.HexToBCD(ulong.Parse(lon.Substring(1, 2).ToString()), 2);
            arr[2] = (byte)GF.HexToBCD(ulong.Parse(lon.Substring(3, 2).ToString()), 2);
            arr[3] = (byte)GF.HexToBCD(ulong.Parse(lon.Substring(5, 2).ToString()), 2);
            arr[4] = (byte)GF.HexToBCD(ulong.Parse(lon.Substring(7, 2).ToString()), 2);
            arr[5] = (byte)GF.HexToBCD(ulong.Parse(lat.Substring(0, 2).ToString()), 2);
            arr[6] = (byte)GF.HexToBCD(ulong.Parse(lat.Substring(2, 2).ToString()), 2);
            arr[7] = (byte)GF.HexToBCD(ulong.Parse(lat.Substring(4, 2).ToString()), 2);
            arr[8] = (byte)GF.HexToBCD(ulong.Parse(lat.Substring(6, 2).ToString()), 2);
            return arr;
        }

        private int MaxRowInTable(DataTable t)
        {
            int i = 0;
            for (i = 0; i < t.Rows.Count; i++)
            {
                if (GF.IsEmpty(t.Rows[i][0]))
                    return i;
            }
            return i;
        }


    //*************************************************************************************************
    }
}
